package cn.virens.web.components.shiro.simple.ajax;

import java.io.IOException;
import java.nio.charset.Charset;

import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;

import cn.hutool.core.util.StrUtil;
import cn.virens.common.CloseableUtil;
import cn.virens.exception.ExceptionUtil;

public class AjaxUtil {
	private static Logger logger = LoggerFactory.getLogger(AjaxUtil.class);
	private static final byte[] EMPTY = new byte[0];
	private static final Charset charset = Charset.forName("UTF-8");

	public static Response failed(Exception ex) {
		return failed(ExceptionUtil.getCode(ex), ExceptionUtil.getMessage(ex));
	}

	public static Response failed(String code, String message) {
		return new Response(code, message, false);
	}

	public static Response success(String code, String message) {
		return new Response(code, message, true);
	}

	public static boolean write(ServletRequest req, ServletResponse resp, Response map) {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;

		ServletOutputStream writer = null;
		try {
			byte[] body = toByte(map);
			String origin = toOrigin(request);

			// 填充跨域头
			response.setHeader("X-Auth-Token", toSession(request));
			response.setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "86400");
			response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
			response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
			response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,OPTIONS");
			response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "X-Auth-Token,Content-Type");

			response.setHeader("Content-Type", "application/json;charset=utf-8");
			response.setHeader("Content-Length", "" + body.length);

			// 输出内容
			writer = response.getOutputStream();
			writer.write(body);
			writer.flush();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		} finally {
			CloseableUtil.close(writer);
		}

		return false;
	}

	private static String toSession(HttpServletRequest request) {
		HttpSession session = request.getSession(true);
		if (session != null) {
			return session.getId();
		} else {
			return null;
		}
	}

	private static String toOrigin(HttpServletRequest request) {
		String origin = request.getHeader("Origin");

		if (StrUtil.isNotEmpty(origin)) {
			return origin;
		} else {
			return "*";
		}
	}

	private static byte[] toByte(Response response) {
		if (response == null) { return EMPTY; }

		StringBuilder builder = new StringBuilder();
		builder.append("{");
		builder.append("\"success\":").append(response.success);
		builder.append(",\"code\":\"").append(response.code).append("\"");
		builder.append(",\"message\":\"").append(response.message).append("\"");
		builder.append("}");

		String bodyStr = builder.toString();

		if (bodyStr != null) {
			return bodyStr.getBytes(charset);
		} else {
			return EMPTY;
		}
	}

	public static class Response {
		private String code;
		private String message;
		private boolean success;

		private Response(String code, String message, boolean success) {
			this.code = code;
			this.message = message;
			this.success = success;
		}

		public boolean isSuccess() {
			return success;
		}

		public void setSuccess(boolean success) {
			this.success = success;
		}

		public String getCode() {
			return code;
		}

		public void setCode(String code) {
			this.code = code;
		}

		public String getMessage() {
			return message;
		}

		public void setMessage(String message) {
			this.message = message;
		}

		@Override
		public String toString() {
			StringBuilder builder = new StringBuilder();
			builder.append("Response [code=");
			builder.append(code);
			builder.append(", message=");
			builder.append(message);
			builder.append(", success=");
			builder.append(success);
			builder.append("]");
			return builder.toString();
		}
	}
}
